
/**
 * AppleIIGo
 * SDL Interface
 * (C) 2007-2008 by Marc S. Ressl (mressl@umich.edu)
 * Released under the GPL
 */

#include <unistd.h>
#include <ctype.h>
#include <stdlib.h>
#include "SDLIO.h"

#define EMULATOR_CHARACTERSET_DEFAULT (1 << 3)
#define EMULATOR_DEFAULT_RESOURCEPATH	"/usr/local/appleiigo/"

static Motherboard * motherboard = NULL;
static SDLIO * sdlio = NULL;
char * resourcesPath;
char * profilePath;

extern "C" void emulatorSetAudioVolume(float value) {	
	sdlio->setAudioVolume(value);
}

extern "C" void emulatorSetVideoFullscreen(unsigned int value) {	
	sdlio->setVideoFullscreen(value);
}

extern "C" void emulatorSetVideoCharacterSet(unsigned int value) {
	sdlio->lock();
	
	VideoRenderer * videoRenderer = motherboard->getVideoRenderer();
	
	videoRenderer->setCharacterSetLanguage(CHARACTERSETGROUP_USER, value);
	if (value & EMULATOR_CHARACTERSET_DEFAULT)
		videoRenderer->setCharacterSetGroup(CHARACTERSETGROUP_DEFAULT);
	else
		videoRenderer->setCharacterSetGroup(CHARACTERSETGROUP_USER);
	
	sdlio->unlock();
}

extern "C" void emulatorSetPause(unsigned int value) {
	sdlio->setThreadPaused(value);
}

extern "C" void emulatorSendReset() {
	sdlio->lock();
	
	motherboard->reset();
	
	sdlio->unlock();
}

extern "C" void emulatorSendRestart() {
	sdlio->lock();
	
	motherboard->restart();
	
	sdlio->unlock();
}

extern "C" unsigned int emulatorMount(char * diskImagePath, 
									  unsigned int driveIndex) {
	sdlio->lock();
	
	bool isOk = motherboard->mount(diskImagePath, driveIndex);

	sdlio->unlock();

	return isOk;
}

extern "C" void emulatorUnmount(unsigned int mountIndex) {
}

extern "C" void emulatorGetMountName(unsigned int mountIndex,
									char * buffer,
									unsigned int bufferSize) {
}

extern "C" unsigned int emulatorIsCopyAvailable() {
	sdlio->lock();
	
	unsigned int isCopyAvailable =
		motherboard->getVideoRenderer()->isCopyAvailable();

	sdlio->unlock();
	
	return isCopyAvailable;
}

extern "C" void emulatorCopy(char * buffer, unsigned int buffersize) {
	sdlio->lock();
	
	motherboard->getVideoRenderer()->copy(buffer, buffersize);

	sdlio->unlock();
}

extern "C" void emulatorPaste(char * buffer) {
	sdlio->lock();
	
	motherboard->getKeyboard()->paste(buffer);
	
	sdlio->unlock();
}

bool readCommandLine(int argc, char * argv[]) {
	resourcesPath = 0;
	profilePath = 0;
	
	char c;
	while ((c = getopt(argc, argv, "hvr:p:")) != -1)
		switch (c) {
			case 'h':
				printf("Usage: appleiigo [options] [diskimage] ...\n");
				printf("Options:\n");
				printf("  -h			Displays this information\n");
				printf("  -v			Displays the program's version\n");
				printf("  -r [path]		Sets AppleIIGo's resources path\n");
				printf("  -p [profile]	Sets AppleIIGo's profile path\n");
				printf("  -f            Starts in fullscreen\n");
				return false;
			case 'v':
				printf("AppleIIGo Version %s (Build %s)\n",
					   APPLEIIGO_VERSION, APPLEIIGO_BUILD);
				return false;
			case 'r':
				resourcesPath = optarg;
				break;
			case 'p':
				profilePath = optarg;
				break;
			case '?':
				if ((optopt == 'r') || (optopt == 'p'))
					fprintf (stderr, "Option -%c requires an argument.\n",
							 optopt);
				else if (isprint(optopt))
					fprintf (stderr, "Unknown option `-%c'.\n",
							 optopt);
				else
					fprintf (stderr, "Unknown option character `\\x%x'.\n",
							 optopt);
				return false;
			default:
				abort();
		}
	
	if (!resourcesPath)
		resourcesPath = EMULATOR_DEFAULT_RESOURCEPATH;
	if (!profilePath) {
		fprintf(stderr, "No profile specified. Please read AppleIIGo's "
				"documentation for more information.");
		return false;
	}
	
	return true;
}

int emulatorRun(int argc, char * argv[]) {
	if (!readCommandLine(argc, argv))
		return 1;
	
	if (!(sdlio = new SDLIO()))
		return 2;
	
	// Loop only when we load a new configuration
	//	while (1) {
	// TO-DO: Read configuration from state file, only specify state file here:
	
	if (!(motherboard = new Motherboard(profilePath, resourcesPath)))
		return 3;
	
	if (argc > 3)
		motherboard->mount(argv[3], 0);
	
	// TO-DO: Fill in SDL Caption
	if (!sdlio->open(motherboard, profilePath))
		return 4;
	sdlio->eventLoop();
	sdlio->close();
	
	delete motherboard;
	delete sdlio;
	
	return 0;
}
